package com.example.elasticstudy;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.javapoet.ClassName;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.*;

@SuppressWarnings("unchecked")
public class ElasticStudy {

    public static void main(String[] args) throws CertificateException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

        makeConnection_truststore();

    }

    private static synchronized void makeConnection_truststore() throws CertificateException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "aE4zkcH4SrVRR2LNZVTl"));
        String path = "E:\\workspace-idea\\elastic-study\\build\\resources\\main\\java-ca.crt";
        System.out.println(path);
        Path caCertificatePath = Paths.get(path);
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Certificate trustedCa;
        try (InputStream is = Files.newInputStream(caCertificatePath)) {
            trustedCa = factory.generateCertificate(is);
        }
        KeyStore trustStore = KeyStore.getInstance("pkcs12");
        trustStore.load(null, null);
        trustStore.setCertificateEntry("ca", trustedCa);
        SSLContextBuilder sslContextBuilder = SSLContexts.custom().loadTrustMaterial(trustStore, null);
        final SSLContext sslContext = sslContextBuilder.build();
        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.181.190", 9200, "https")).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                return httpClientBuilder.setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setDefaultCredentialsProvider(credentialsProvider);
            }
        });
        RestClient restClient = builder.build();
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        ElasticsearchClient client = new ElasticsearchClient(transport);
        ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(transport);
        /************************索引管理*************************************/
        //创建索引
        CreateIndexRequest request = new CreateIndexRequest.Builder().index("myindex222").build();
        final CreateIndexResponse createIndexResponse = client.indices().create(request);
        System.out.println("创建索引成功：" + createIndexResponse.acknowledged());

        // 查询索引
        GetIndexRequest getIndexRequest = new GetIndexRequest.Builder().index("myindex222").build();
        final GetIndexResponse getIndexResponse = client.indices().get(getIndexRequest);
        System.out.println("索引查询成功：" + getIndexResponse.result());

        // 删除索引
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index("myindex222").build();
        final DeleteIndexResponse delete = client.indices().delete(deleteIndexRequest);
        final boolean acknowledged = delete.acknowledged();
        System.out.println("删除索引成功：" + acknowledged);

        /************************文档操作*********************************/
        Map<String, String> user = new HashMap<>();
        user.put("id", "001");
        user.put("name", "name");
        // 创建文档
        IndexRequest indexRequest = new IndexRequest.Builder().index("myindex").id(user.get("id")).document(user).build();
        final IndexResponse index = client.index(indexRequest);
        System.out.println("文档操作结果:" + index.result());
        // 批量创建文档
        final List<BulkOperation> operations = new ArrayList<BulkOperation>();
        for (int i = 1; i <= 20; i++) {
            final CreateOperation.Builder builder1 = new CreateOperation.Builder();
            builder1.index("myindex");
            builder1.id("200" + i);
            user.put("100" + i, "name" + i);

            builder1.document(user);
            final CreateOperation<Object> objectCreateOperation = builder1.build();
            final BulkOperation bulk = new BulkOperation.Builder().create(objectCreateOperation).build();
            operations.add(bulk);
        }
        BulkRequest bulkRequest = new BulkRequest.Builder().operations(operations).build();
        final BulkResponse bulkResponse = client.bulk(bulkRequest);
        System.out.println("数据操作成功：" + bulkResponse);
        // 删除文档
        DeleteRequest deleteRequest = new DeleteRequest.Builder().index("myindex").id("1001").build();
        client.delete(deleteRequest);

        /******************************文档查询****************************************/
        final SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder().index("myindex");
        MatchQuery matchQuery = new MatchQuery.Builder().field("city").query(FieldValue.of("shanghai")).build();
        Query query = new Query.Builder().match(matchQuery).build();
        searchRequestBuilder.query(query);
        SearchRequest searchRequest = searchRequestBuilder.build();
        final SearchResponse<Object> search = client.search(searchRequest, Object.class);
        System.out.println(search);

        /*******************************函数操作*********************************************/
        // 创建索引
        final Boolean acknowledged1 = client.indices().create(p -> p.index("myindex1")).acknowledged();
        System.out.println("创建索引成功");
        // 获取索引
        System.out.println(client.indices().get(req -> req.index("myindex1")).result());
        // 删除索引
        client.indices().delete(reqbuilder -> reqbuilder.index("myindex1")).acknowledged();

        /**************************************文档操作***************************************/
        // 创建文档
//        System.out.println(client.index(req -> req.index("myindex").id(user.get("id")).document(user)).result());
        List<Map<String,String>> users = new ArrayList<>();
        Map<String,String> user1 =  new HashMap<>();
        user1.put("id","3001");
        user1.put("name","name3001");
        Map<String,String> user2 =  new HashMap<>();
        user2.put("id","3002");
        user2.put("name","name3002");
        Map<String,String> user3 =  new HashMap<>();
        user3.put("id","3003");
        user3.put("name","name3003");
        Map<String,String> user4 =  new HashMap<>();
        user4.put("id","3004");
        user4.put("name","name3004");
        Map<String,String> user5 =  new HashMap<>();
        user5.put("id","3005");
        user5.put("name","name3005");
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);

        // 批量创建文档
        client.bulk(req -> {
            users.forEach(u -> {
                req.operations(b -> {
                    b.create(d -> d.id(u.get("id").toString()).index("myindex").document(u));
                    return b;
                });
            });
            return req;
        });

        // 删除文档
        client.delete(req -> req.index("myindex").id("1001"));

        /**************************************客户端异步操作***************************************/
        // 创建索引
        asyncClient.indices().create(
                        req -> {
                            req.index("newindex");
                            return req;
                        }
                )
                .thenApply(
                        resp -> {
                            return resp.acknowledged();
                        }
                )
                .whenComplete(
                        (resp, error) -> {
                            System.out.println("回调函数");
                            if ( !resp ) {
                                System.out.println();
                            } else {
                                error.printStackTrace();
                            }
                        }
                );
        transport.close();
    }








}
